﻿using EMC.VISITOR.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EMC.EQUI.Core
{
    public abstract class AutoMatedStorageService : IAutoMatedStorageService
    {
        private readonly SqlSugarRepository<Location> _repLocation;
        protected AutoMatedStorageService(SqlSugarRepository<Location> repLocation)
        {
            _repLocation = repLocation;
        }
        private async void CreateStackerTask(List<CreateStackerTaskDto> dto)
        {

        }
        public async Task<bool> EnterStorage(EnterStorageDto dto)
        {
            throw new NotImplementedException();
        }

        public async Task<bool> MoveStorage(List<MoveStorageDto> dto)
        {
            var locations = await GetLocations();
            ////获取中转储位
            //var transferLocations = locations.Where(r => r.CanInTransferStation()).Take(dto.Count).ToList();
            ////锁定中转储位
            //transferLocations.ForEach(r => r.);

            return false;
        }

        public async Task<bool> OutStorage(List<OutStorageDto> dto)
        {
            var allLications = await GetCanOutLocations();
            //找到需要出库的库位
            var locations = allLications.Where(r => r.CanOut() && dto.Select(c => c.AliasCode).Contains(r.AliasCode)).OrderBy(r => r.ExitorMax).OrderBy(r => r.ColumnNum).ToList();
            if (locations.Count <= 0) { return false; }

            List<Task> taskList = new List<Task>();
            foreach (var location in locations)
            {
                //锁定库位，需要等待堆垛机任务执行完毕后释放该库位
                location.IsOutEnterStatus = IsOutEnterStatus.Lock;
                location.Remark = $"【{location.Symbol}-{location.AliasCode}】出库中...";
                //判断是否需要移库
                var moveLocations = location.NeedMoveLocationRowColumnLayer();

                if (moveLocations.Count > 0) //需要移库
                {
                    //确定要移库的那些库位是否能出库
                    moveLocations = allLications.Where(r => moveLocations.Select(c => c.AliasCode).Contains(r.AliasCode) && r.CanOut()).ToList();
                    if (moveLocations.Count > 0)
                    {
                        var needMoveStorageDtos = moveLocations.Select(targetLocation => new MoveStorageDto
                        {
                            WarehouseCode = targetLocation.WarehouseCode,
                            WarehouseType = targetLocation.WarehouseType,
                            ZoneCode = targetLocation.ZoneCode,
                            AliasCode = targetLocation.AliasCode
                        }).ToList();
                        taskList.Add(MoveStorage(needMoveStorageDtos));
                        location.Remark += $",等待移库【{string.Join(",", needMoveStorageDtos.Select(r => r.AliasCode).ToList())}】";
                    }
                }
            }
            await Task.WhenAll(taskList.ToArray());
            //如果有移库操作，需要先执行完成上面的移库，然后才能执行如下的出库
            CreateStackerTask(locations.Select(r => new CreateStackerTaskDto { Location = r, StockerTaskType = StockerTaskType.出库 }).ToList());

            await _repLocation.Context.MyUpdateable<Location>(locations).UpdateColumns(r => new
            {
                r.IsOutEnterStatus,
                r.Remark
            }).ExecuteCommandAsync();
            return true;
        }

        public async Task<List<Location>> GetLocations(Expression<Func<Location, bool>> expression = null)
        {
            return await _repLocation.Context.MyQueryable<Location>().Where(expression).ToListAsync();
        }
        /// <summary>
        /// 获取能出库所有库位
        /// </summary>
        /// <returns></returns>
        public async Task<List<Location>> GetCanOutLocations()
        {
            IsOutEnterStatus[] outEnterStatusList = new IsOutEnterStatus[] { IsOutEnterStatus.Out };
            var allLications = await GetLocations(r => r.IsEnabled == true && outEnterStatusList.Contains(r.IsOutEnterStatus) && r.LocationGroupType == LocationGroupType.Normal);
            return allLications;
        }

    }
}
